package com.supermap.panes;

import com.supermap.Helper;
import com.supermap.MainFrame;
import com.supermap.analyst.spatialanalyst.SmoothMethod;
import com.supermap.analyst.spatialanalyst.SurfaceAnalyst;
import com.supermap.analyst.spatialanalyst.SurfaceExtractParameter;
import com.supermap.data.*;
import com.supermap.data.Enum;
import com.supermap.dialogs.ProcessBarDialog;
import com.supermap.panes.advance.SettingPane;

import javax.swing.*;
import java.awt.*;

public class ExtractIsoLineOrRegionSettingPane extends SettingPane {
    private JComboBox<String> srcDatasourceNameCmb;
    private JComboBox<String> srcDatasetNameCmb;
    private JTextField datumValueTxt;
    private JTextField intervalTxt;
    private JTextField resampleToleranceTxt;
    private JComboBox<SmoothMethod> smoothMethodCmb;
    private JTextField smoothnessTxt;
    private JCheckBox useBarrierDatasetCbx;
    private JComboBox<String> barrierDatasourceCmb;
    private JComboBox<String> barrierDatasetCmb;
    private JComboBox<String> resultDatasourceNameCmb;
    private JTextField resultDatasetNameTxt;

    private Workspace workspace;
    private SteppedListener steppedListener;
    private ProcessBarDialog processBarDialog;
    private boolean isLine;

    public ExtractIsoLineOrRegionSettingPane(String title, Workspace workspace, boolean isLine) {
        super(title, new Object[]{workspace, isLine});
    }

    @Override
    protected void initializeArgs(Object[] args) {
        this.workspace = (Workspace) args[0];
        this.isLine = (boolean) args[1];
        steppedListener = steppedEvent -> {
            if (processBarDialog == null) {
                return;
            }
            int percent = steppedEvent.getPercent();
            processBarDialog.setValue(percent);
            if (percent == 100) {
                processBarDialog.setVisible(false);
                processBarDialog.dispose();
                processBarDialog = null;
                JOptionPane.showMessageDialog(getRootPane().getParent(), "等值" + (isLine ? "线" : "面") + "提取完成!", "提取所有" + (isLine ? "线" : "面"), JOptionPane.INFORMATION_MESSAGE);
            }
        };
    }

    @Override
    protected void initializeCore() {
        if (workspace == null) {
            return;
        }

        JPanel settingPanel = new JPanel();
        settingPanel.setLayout(new GridBagLayout());
        super.mainPanel.add(settingPanel);

        JPanel srcDataPanel = new JPanel();
        srcDataPanel.setBorder(BorderFactory.createTitledBorder("源数据"));
        srcDataPanel.setLayout(new GridBagLayout());
        settingPanel.add(srcDataPanel, new GridBagConstraints(0, 0, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));

        JLabel srcDatasourceLbl = new JLabel("数据源: ");
        srcDataPanel.add(srcDatasourceLbl, new GridBagConstraints(0, 0, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        srcDatasourceNameCmb = new JComboBox<>();
        srcDataPanel.add(srcDatasourceNameCmb, new GridBagConstraints(1, 0, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        Datasources datasources = workspace.getDatasources();
        int datasourcesCount = datasources.getCount();
        if (datasourcesCount > 0) {
            for (int i = 0; i < datasourcesCount; i++) {
                Datasource datasource = datasources.get(i);
                srcDatasourceNameCmb.addItem(datasource.getAlias());
            }
        }
        srcDatasourceNameCmb.addItemListener(e -> {
            String datasourceName = (String) e.getItem();
            reloadDatasetCmb(datasources, datasourceName);
        });

        JLabel srcDatasetLbl = new JLabel("数据集: ");
        srcDataPanel.add(srcDatasetLbl, new GridBagConstraints(0, 1, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        srcDatasetNameCmb = new JComboBox<>();
        srcDataPanel.add(srcDatasetNameCmb, new GridBagConstraints(1, 1, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        if (srcDatasourceNameCmb.getItemCount() > 0) {
            String srcDatasourceName = (String) srcDatasourceNameCmb.getSelectedItem();
            reloadDatasetCmb(datasources, srcDatasourceName);
        }

        JPanel parametersPanel = new JPanel();
        parametersPanel.setBorder(BorderFactory.createTitledBorder("参数设置"));
        parametersPanel.setLayout(new GridBagLayout());
        settingPanel.add(parametersPanel, new GridBagConstraints(0, 1, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));

        JLabel datumValueLbl = new JLabel("基准值: ");
        parametersPanel.add(datumValueLbl, new GridBagConstraints(0, 0, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        datumValueTxt = new JTextField();
        datumValueTxt.setText("0");
        parametersPanel.add(datumValueTxt, new GridBagConstraints(1, 0, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel intervalLbl = new JLabel("等值距: ");
        parametersPanel.add(intervalLbl, new GridBagConstraints(0, 1, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        intervalTxt = new JTextField();
        intervalTxt.setText("100");
        parametersPanel.add(intervalTxt, new GridBagConstraints(1, 1, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel resampleToleranceLbl = new JLabel("重采样系数: ");
        parametersPanel.add(resampleToleranceLbl, new GridBagConstraints(0, 2, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        resampleToleranceTxt = new JTextField();
        resampleToleranceTxt.setText("0");
        parametersPanel.add(resampleToleranceTxt, new GridBagConstraints(1, 2, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel smoothMethodLbl = new JLabel("光滑方法: ");
        parametersPanel.add(smoothMethodLbl, new GridBagConstraints(0, 3, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        smoothMethodCmb = new JComboBox<>();
        parametersPanel.add(smoothMethodCmb, new GridBagConstraints(1, 3, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        Enum[] enums = SmoothMethod.getEnums(SmoothMethod.class);
        for (Enum anEnum : enums) {
            smoothMethodCmb.addItem((SmoothMethod) anEnum);
        }
        smoothMethodCmb.addItemListener(e -> {
            SmoothMethod smoothMethod = (SmoothMethod) e.getItem();
            smoothnessTxt.setEnabled(smoothMethod != SmoothMethod.NONE);
        });

        JLabel smoothnessLbl = new JLabel("光滑系数: ");
        parametersPanel.add(smoothnessLbl, new GridBagConstraints(0, 4, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        smoothnessTxt = new JTextField();
        smoothnessTxt.setText("2");
        parametersPanel.add(smoothnessTxt, new GridBagConstraints(1, 4, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        smoothnessTxt.setEnabled(smoothMethodCmb.getSelectedItem() != SmoothMethod.NONE);

        JLabel useBarrierDataset = new JLabel("是否启用障碍数据:");
        parametersPanel.add(useBarrierDataset, new GridBagConstraints(0, 5, 2, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        useBarrierDatasetCbx = new JCheckBox();
        useBarrierDatasetCbx.setSelected(false);
        useBarrierDatasetCbx.addItemListener(e -> {
            boolean selected = ((JCheckBox) e.getItem()).isSelected();
            barrierDatasourceCmb.setEnabled(selected);
            barrierDatasetCmb.setEnabled(selected);
        });
        parametersPanel.add(useBarrierDatasetCbx, new GridBagConstraints(1, 5, 2, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel barrierDatasourceLbl = new JLabel("障碍数据源: ");
        parametersPanel.add(barrierDatasourceLbl, new GridBagConstraints(0, 6, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        barrierDatasourceCmb = new JComboBox<>();
        barrierDatasourceCmb.setEnabled(false);
        if (datasourcesCount > 0) {
            for (int i = 0; i < datasourcesCount; i++) {
                Datasource datasource = datasources.get(i);
                barrierDatasourceCmb.addItem(datasource.getAlias());
            }
        }
        barrierDatasourceCmb.addItemListener(e -> {
            String datasourceName = (String) e.getItem();
            reloadBarrierDatasetCmb(datasources, datasourceName);
        });
        parametersPanel.add(barrierDatasourceCmb, new GridBagConstraints(1, 6, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel barrierDatasetLbl = new JLabel("障碍数据集: ");
        parametersPanel.add(barrierDatasetLbl, new GridBagConstraints(0, 7, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        barrierDatasetCmb = new JComboBox<>();
        barrierDatasetCmb.setEnabled(false);
        if (barrierDatasourceCmb.getItemCount() > 0) {
            String barrierDatasourceName = (String) barrierDatasourceCmb.getSelectedItem();
            reloadBarrierDatasetCmb(datasources, barrierDatasourceName);
        }
        parametersPanel.add(barrierDatasetCmb, new GridBagConstraints(1, 7, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JPanel resultPanel = new JPanel();
        resultPanel.setBorder(BorderFactory.createTitledBorder("结果数据"));
        resultPanel.setLayout(new GridBagLayout());
        settingPanel.add(resultPanel, new GridBagConstraints(0, 2, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        JLabel resultDatasourceNameLbl = new JLabel("数据源: ");
        resultPanel.add(resultDatasourceNameLbl, new GridBagConstraints(0, 0, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        resultDatasourceNameCmb = new JComboBox<>();
        resultPanel.add(resultDatasourceNameCmb, new GridBagConstraints(1, 0, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        if (srcDatasourceNameCmb.getItemCount() > 0) {
            for (int i = 0; i < srcDatasourceNameCmb.getItemCount(); i++) {
                String datasourceName = srcDatasourceNameCmb.getItemAt(i);
                resultDatasourceNameCmb.addItem(datasourceName);
            }
        }

        JLabel resultDatasetNameLbl = new JLabel("数据集: ");
        resultPanel.add(resultDatasetNameLbl, new GridBagConstraints(0, 1, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        resultDatasetNameTxt = new JTextField();
        resultPanel.add(resultDatasetNameTxt, new GridBagConstraints(1, 1, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        if (resultDatasourceNameCmb.getItemCount() > 0) {
            String datasourceName = (String) resultDatasourceNameCmb.getSelectedItem();
            Datasource datasource = datasources.get(datasourceName);
            String availableDatasetName = datasource.getDatasets().getAvailableDatasetName("result_ISO" + (isLine ? "Line" : "Region"));
            resultDatasetNameTxt.setText(availableDatasetName);
        }
    }

    @Override
    protected void doConfirm() {
        if (srcDatasourceNameCmb.getItemCount() == 0 || srcDatasetNameCmb.getItemCount() == 0 || resultDatasourceNameCmb.getItemCount() == 0) {
            return;
        }

        String srcDatasourceName = (String) srcDatasourceNameCmb.getSelectedItem();
        Datasources datasources = workspace.getDatasources();
        Datasource datasource = datasources.get(srcDatasourceName);
        String srcDatasetName = (String) srcDatasetNameCmb.getSelectedItem();
        DatasetGrid extractedGrid = (DatasetGrid) datasource.getDatasets().get(srcDatasetName);
        String resultDatasourceName = (String) resultDatasourceNameCmb.getSelectedItem();
        Datasource targetDatasource = datasources.get(resultDatasourceName);

        SurfaceExtractParameter surfaceExtractParameter = new SurfaceExtractParameter();
        surfaceExtractParameter.setDatumValue(Double.parseDouble(datumValueTxt.getText()));
        surfaceExtractParameter.setInterval(Double.parseDouble(intervalTxt.getText()));
        surfaceExtractParameter.setSmoothness(Integer.parseInt(smoothnessTxt.getText()));
        surfaceExtractParameter.setResampleTolerance(Double.parseDouble(resampleToleranceTxt.getText()));
        surfaceExtractParameter.setSmoothMethod((SmoothMethod) smoothMethodCmb.getSelectedItem());

        SurfaceAnalyst.addSteppedListener(steppedListener);
        if (processBarDialog == null) {
            processBarDialog = new ProcessBarDialog((Frame) getRootPane().getParent(), "提取所有" + (isLine ? "线" : "面"), true);
        }
        new Thread(() -> {
            DatasetVector datasetVector;
            if (isLine) {
                if (!useBarrierDatasetCbx.isSelected()) {
                    datasetVector = SurfaceAnalyst.extractIsoline(surfaceExtractParameter, extractedGrid, targetDatasource,
                            resultDatasetNameTxt.getText());
                } else {
                    Datasource barrierDatasource = workspace.getDatasources().get((String) barrierDatasourceCmb.getSelectedItem());
                    DatasetVector barrierDatasetVector = (DatasetVector) barrierDatasource.getDatasets().get((String) barrierDatasetCmb.getSelectedItem());
                    datasetVector = SurfaceAnalyst.extractIsoline(surfaceExtractParameter, extractedGrid, targetDatasource,
                            resultDatasetNameTxt.getText(), barrierDatasetVector);
                }
            } else {
                datasetVector = SurfaceAnalyst.extractIsoregion(surfaceExtractParameter, extractedGrid, targetDatasource,
                        resultDatasetNameTxt.getText(), extractedGrid.getClipRegion());
            }
            if (datasetVector != null) {
                MainFrame mainFrame = (MainFrame) getRootPane().getParent();
                Helper.addDatasetToNewMap(datasetVector, mainFrame);
            }
        }).start();
        processBarDialog.setVisible(true);
    }

    @Override
    protected void doClose() {
        if (processBarDialog != null) {
            processBarDialog = null;
        }
        SurfaceAnalyst.removeSteppedListener(steppedListener);
    }

    private void reloadDatasetCmb(Datasources datasources, String srcDatasourceName) {
        Datasource datasource = datasources.get(srcDatasourceName);
        Datasets datasets = datasource.getDatasets();
        if (datasets != null && datasets.getCount() > 0) {
            for (int i = 0; i < datasets.getCount(); i++) {
                Dataset dataset = datasets.get(i);
                if (dataset instanceof DatasetGrid) {
                    srcDatasetNameCmb.addItem(dataset.getName());
                }
            }
        }
    }

    private void reloadBarrierDatasetCmb(Datasources datasources, String srcDatasourceName) {
        Datasource datasource = datasources.get(srcDatasourceName);
        Datasets datasets = datasource.getDatasets();
        if (datasets != null && datasets.getCount() > 0) {
            for (int i = 0; i < datasets.getCount(); i++) {
                Dataset dataset = datasets.get(i);
                DatasetType datasetType = dataset.getType();
                if (datasetType == DatasetType.LINE) {
                    barrierDatasetCmb.addItem(dataset.getName());
                }
            }
        }
    }
}
